package main

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"os/exec"
	"strconv"
)

func ParseEnvVar(configFile string, variableName string) string {
	// create a bash shell to load environment variables
	command := "source " + configFile + " && echo -n $" + variableName
	cmd := exec.Command("/bin/bash", "-c", command)
	output, err := cmd.Output()
	if err != nil {
		fmt.Println("source configFile err:", err)
		return ""
	}
	// fmt.Println("command output:", string(output))
	return string(output)
}

func ParseEnvVarArray(configFile string, variablesName string) []string {
	// create a bash shell to load environment variables
	command := "source " + configFile + " && echo ${" + variablesName + "[@]}"
	cmd := exec.Command("/bin/bash", "-c", command)
	output, err := cmd.Output()
	if err != nil {
		fmt.Println("source configFile err:", err)
		return nil
	}
	// parse output
	var envArray []string
	var envVar string
	for _, c := range output {
		if c == ' ' || c == '\n' {
			if envVar != "" {
				envArray = append(envArray, envVar)
				envVar = ""
			}
		} else {
			envVar += string(c)
		}
	}
	return envArray
}

func GetCephClusterIP(clusterID int) string {
	return ClusterIp(clusterID)
}

func GetCephClusterPort(clusterID int) string {
	return CephServerPortPrefix + strconv.Itoa(clusterID)
}

func GetCephClusterIPPort(clusterID int) string {
	return ClusterIp(clusterID) + ":" + GetCephClusterPort(clusterID)
}

func ClusterIp(clusterID int) string {
	if clusterID < 0 || clusterID >= ClusterNum {
		return ""
	}
	return CephIPs[clusterID]
}

func KafkaIPPort() string {
	return KafkaIP + ":" + KafkaPort
}

func GetFabricSDKIPPort() string {
	return FabricSDKIP + ":" + FabricSDKPort
}

// func GetCAcert(clusterID int) string {
// 	if clusterID < 0 || clusterID >= ClusterNum {
// 		return ""
// 	}
// 	// clusterID {0-3} 对应组织 org{1-4}
// 	caCert := CryptoFilesPath + "peerOrganizations/org" + strconv.Itoa(clusterID+1) + ".demo.com/peers/peer0.org" + strconv.Itoa(clusterID+1) + ".demo.com/tls/ca.crt"
// 	return caCert
// }

// func GetCert(clusterID int) string {
// 	if clusterID < 0 || clusterID >= ClusterNum {
// 		return ""
// 	}
// 	// clusterID {0-3} 对应组织 org{1-4}
// 	Cert := CryptoFilesPath + "peerOrganizations/org" + strconv.Itoa(clusterID+1) + ".demo.com/peers/peer0.org" + strconv.Itoa(clusterID+1) + ".demo.com/tls/server.crt"
// 	return Cert
// }

// func GetPriKey(clusterID int) string {
// 	if clusterID < 0 || clusterID >= ClusterNum {
// 		return ""
// 	}
// 	// clusterID {0-3} 对应组织 org{1-4}
// 	priKey := CryptoFilesPath + "peerOrganizations/org" + strconv.Itoa(clusterID+1) + ".demo.com/peers/peer0.org" + strconv.Itoa(clusterID+1) + ".demo.com/tls/server.key"
// 	return priKey
// }

func PrefixDealObj(clusterID int) string {
	if clusterID < 0 || clusterID >= ClusterNum {
		return ""
	}
	// return "http://peer0.org" + strconv.Itoa(clusterID+1) + ".demo.com:" + GetCephClusterPort(clusterID) + "/"
	return "http://" + GetCephClusterIPPort(clusterID) + "/"
}

// func addTrustCAcert(pool *x509.CertPool, path string) {
// 	aCrt, err := ioutil.ReadFile(path)
// 	if err != nil {
// 		fmt.Println("ReadFile err:", err)
// 		return
// 	}
// 	pool.AppendCertsFromPEM(aCrt)
// }

func checkDataWithMerkleProof(dataWithProof *DataWithProof, data4Koffset int) bool {
	hash := sha256.New()
	hash.Write(dataWithProof.Data)
	hashRes := hash.Sum(nil)
	// hash := sha256.New().Sum(dataWithProof.Data)
	if ObjectSize == 4*1024*1024 {
		if !bytes.Equal(hashRes, dataWithProof.Proof.Proof[0][data4Koffset%32]) {
			fmt.Printf("cluster [%d] -> failed to check data in merkle proof, dataHash: %v, proofHash: %v\n", *ClusterID, hashRes, dataWithProof.Proof.Proof[0][data4Koffset%32])
			return false
		}
		if !dataWithProof.Proof.Check(data4Koffset) {
			fmt.Printf("cluster [%d] -> failed to check merkle proof, offset=%d: \n", *ClusterID, data4Koffset)
			return false
		}
	} else {
		if !bytes.Equal(hashRes, dataWithProof.Proof.Proof[0][0]) {
			fmt.Printf("cluster [%d] -> failed to check data in merkle proof, dataHash: %v, proofHash: %v\n", *ClusterID, hashRes, dataWithProof.Proof.Proof[0][data4Koffset%32])
			return false
		}
	}
	
	return true
}

func StrHashToNum(str string, mod int) int {
	var sum int
	for _, s := range str {
		sum += int(s)
	}
	return sum % mod
}
